/* CS32 FINAL PROJECT */

package GameEngine;

/**
 * 2D vector for ease of vector operations.
 * @author mhfowler
 */
public class Vector {

    // data
    float x;
    float y;

    public Vector(float a, float b) {
        x = a;
        y = b;
    }

    public Vector(Vector v) {
        x = v.getX();
        y = v.getY();
    }

    public Vector(double a, double b) {
        x = (float) a;
        y = (float) b;
    }

    // vector math
    public void add(Vector v) {
        x += v.x;
        y += v.y;
    }

    public void add(float a, float b) {
        x += a;
        y += b;
    }

    public void scale(float k) {
        x = k*x;
        y = k*y;
    }

    public Vector scaleNew(float k) {
       return new Vector(k*x, k*y);
    }

    public void scale(double k) {
        Float kFloat = (float) k;
        x = kFloat * x;
        y = kFloat * y;
    }
    public void scale(double j, double k) {
        x = (float) (j * x);
        y = (float) (k * y);
    }

    public Vector scaleNew(double k) {
        Float kFloat = (float) k;
        return new Vector(kFloat * x, kFloat * y);
    }

    public Vector addNew(Vector v) {
        Vector toReturn = new Vector(x, y);
        toReturn.add(v);
        return toReturn;
    }

    public Vector addNew(float a, float b) {
        Vector toReturn = new Vector(x, y);
        toReturn.add(a,b);
        return toReturn;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }

    // returns true if x and y of this
    // are greater than x and y of v
    boolean greaterThan(Vector v) {
       return (x > v.x && y > v.y);
    }

    // returns true if x and y of this
    // are less than x and y of v
    boolean lessThan(Vector v) {      
      return (x < v.x && y < v.y);
    }



    /* gets magnitude of vector */
    /*
    public double getNorm() {
        return Math.sqrt((double) x*x + y*y);
    }

    */
    /* get unit vector */
    public Vector unitNew() {
        return (scaleNew(1/getNorm()));
    }


    // takes in a number of degrees and rotates the vector by that many radians counter-clockwise and returns new vector
    public void rotate(int radians) {
        x = (float) (x * Math.cos(radians) - y * Math.sin(radians));
        y = (float) (x * Math.sin(radians) + y * Math.cos(radians));
    }


    /* returns the angle in radians between this vector and the inputted vector */
    /* note, returns a value between 0 and 180 */
    public double getTheta(Vector v) {
        float dotproduct = x*v.getX() + y*v.getY();
        float mag = (float) (this.getNorm() * v.getNorm());
        return Math.acos(dotproduct/mag);
    }

    /**
     * Returns the dot product of this and another vector
     * @param v
     * @return
     */
    public float dotProduct(Vector v) {
        return v.getX() * x + v.getY() * y;
    }

    /**
     * Returns the norm of this vector
     * @return
     */

    public float getNorm() {
        return (float) Math.sqrt(dotProduct(this));
    }
    
    /**
     * Gets the projection of this vector onto another vector
     * @param v
     * @return
     */

    public Vector project(Vector v) {
        if (x == 0 && y == 0) {
            return new Vector(0, 0);
        } else {
            // project onto vector
            float linear = this.dotProduct(v) / v.getNorm();
            // then project back onto euclidean coordinates
            return v.scaleNew(linear / this.getNorm());
        }
    }

    public float projectScalar(Vector v) {

        return this.dotProduct(v)/(v.getNorm());
    }

    /**
     * Gets a Vector that is orthogonal to this one
     */

    public Vector getOrthog() {
        return new Vector(y, -x);
    }



    public String toString() {
        String toReturn = "{";
        toReturn += x + "," + y + "}";
        return toReturn;
    }




}
